<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="Generator" content="EditPlus®">
    <meta name="Author" content="ZhangBin">
    <meta name="Keywords" content="粒子效果,canvas,canvas粒子效果,连线粒子,粒子与鼠标,粒子吸附,粒子吸附鼠标,粒子吸附光标,">
    <meta name="Description" content="">
    <title>Document</title>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }

        body {
            font-size: 14px;
        }

        a {
            text-decoration: none;
            font-size: 14px;
            color: #fff;
        }

        ul li, ol li {
            list-style-type: none;
        }

        #can {
            background-color: #000;
            display: block;
        }
    </style>
</head>

<body>
<div class="container">
    <canvas id="can"></canvas>
</div>

<script type="text/javascript">
    var can = document.getElementById("can");
    //设置canvas宽高
    var x = w = can.width = window.innerWidth;
    var y = h = can.height = window.innerHeight;
    //获取绘画环境
    var ctx = can.getContext("2d");
    //初始化参数
    var pointNum = 200;//点的个数
    var data = [];//用来存储上以一个瞬间点的坐标
    var Dvalue = 50;//连线距离
    var line_strokeStyle = "#f6f";//连线颜色（无效）//采用渐变颜色
    var circle_strokeStyle = "#f6f";//点颜色
    var circle_R = 2;//点的大小
    var speed_x = 4;//点在X方向移动速度
    var speed_y = 4;//点在y方向移动速度
    var mouse = {};//用来存储鼠标的位置
    var adsorbScope = 100;//吸附范围
    var isAdsorb = false;//是否被吸附
    switch (true) {
        case w >= 1920 :
            pointNum = 350;
            break;
        case w >= 1680 :
            pointNum = 280;
            break;
        case w >= 1440 :
            pointNum = 250;
            break;
        case w >= 1024 :
            pointNum = 200;
            break;
        default :
            pointNum = 180;
            break;
    }

    //鼠标移动事件
    document.onmousemove = function (e) {
        mouse.x = e.pageX;
        mouse.y = e.pageY;
        for (var i = 0; i < pointNum; i++) data[i].isAdsorb = isAdsorb;
    }
    //鼠标移除事件
    document.onmouseleave = function () {
        mouse = {};
        for (var i = 0; i < pointNum; i++) data[i].isAdsorb = isAdsorb;
    }
    window.onresize = function (e) {
        x = w = can.width = window.innerWidth;
        y = h = can.height = window.innerHeight;
        for (var i = 0; i < pointNum; i++) {
            if (data[i].x > w) data[i].x = w;
            if (data[i].x < 0) data[i].x = 0;
            if (data[i].y < 0) data[i].y = 0;
            if (data[i].y > h) data[i].y = h;
        }
    }

    for (var i = 0; i < pointNum; i++) {
        //获取随机的圆心坐标
        var circle_x = Math.random() * x;
        var circle_y = Math.random() * y;
        //将每个圆的圆形坐标当成一个对象存到数组中
        data[i] = {};
        data[i].x = circle_x;
        data[i].y = circle_y;
        //每个点的移动速度是随机的
        data[i].speedX = Math.random() * speed_x - 2;
        data[i].speedY = Math.random() * speed_y - 2;
        data[i].isAdsorb = isAdsorb;//没被吸附
        getCircle(data[i].x, data[i].y, circle_R, 0, 2 * Math.PI, true, circle_strokeStyle)
    }

    ;(function draw() {
        //清除画板
        ctx.clearRect(0, 0, x, y);
        //重新圆点
        for (var i = 0; i < pointNum; i++) {
            //将每个圆的圆形坐标当成一个对象存到数组中(每次都将上一次运动的圆点的坐标修改并存储起来)
            //每次都在上一次位置的基础上改变坐标（视觉让我们觉得点在移动）
            data[i].x += data[i].speedX;
            data[i].y += data[i].speedY;
            if (data[i].x > w || data[i].x < 0) {//到边界之后反弹回来
                data[i].speedX = -data[i].speedX;
            }
            if (data[i].y > h || data[i].y < 0) {
                data[i].speedY = -data[i].speedY;
            }
            getCircle(data[i].x, data[i].y, circle_R, 0, 2 * Math.PI, true, circle_strokeStyle)
            //判断点与点之间的就距离，如果小于50px则直线连接
            for (var j = i + 1; j < pointNum; j++) {
                if (Math.pow(data[i].x - data[j].x, 2) + Math.pow(data[i].y - data[j].y, 2) <= Math.pow(Dvalue, 2)) {
                    getLine(data[i].x, data[i].y, data[j].x, data[j].y, line_strokeStyle)
                }
            }
            if (mouse.x && mouse.y) {
                var l = Math.pow(mouse.x - data[i].x, 2) + Math.pow(mouse.y - data[i].y, 2);
                if (data[i].isAdsorb) {//被吸附
                    if (l > Math.pow(adsorbScope, 2)) {
                        data[i].speedX = -data[i].speedX;
                        data[i].speedY = -data[i].speedY;
                    }
                } else if (l <= Math.pow(adsorbScope, 2)) {//没有被吸附的，但是即将被吸附的
                    data[i].isAdsorb = true;
                }
            }


        }
        window.requestAnimationFrame(draw);
    })()

    //画圆
    function getCircle(x, y, r, beginR, endR, order, styleColor) {
        ctx.fillStyle = styleColor
        ctx.beginPath();
        ctx.arc(x, y, r, beginR, endR, order);
        ctx.closePath();
        ctx.fill();
    }

    //画直线
    function getLine(x1, y1, x2, y2, strokeStyle) {
        //采用渐变颜色
        var line = ctx.createLinearGradient(x1, y1, x2, y2);
        line.addColorStop(0, "#6600ff");
        line.addColorStop(0.5, "#00cc33");
        line.addColorStop(1, "#ff0099")
        ctx.strokeStyle = line;
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.stroke();
    }

</script>
</body>
</html>
